{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "ba85ab13",
   "metadata": {},
   "source": [
    "### Misexpression metrics \n",
    "\n",
    "* Total number and proportion of misexpression events across different z-score cutoffs \n",
    "* Proportion of genes with at least one misexpression event across different cutoffs \n",
    "* Proportion of samples that have a misexpression events across different "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "ce2f3e78",
   "metadata": {},
   "outputs": [],
   "source": [
    "from pathlib import Path\n",
    "import pandas as pd\n",
    "import random\n",
    "import matplotlib.pyplot as plt\n",
    "import seaborn as sns"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "8de8a319",
   "metadata": {},
   "outputs": [],
   "source": [
    "wkdir = \"/lustre/scratch126/humgen/projects/interval_rna/interval_rna_seq/thomasVDS/misexpression_v3/\"\n",
    "wkdir_path = Path(wkdir)\n",
    "input_dir= wkdir_path.joinpath(\"2_misexp_qc\")\n",
    "covariates_path = \"/lustre/scratch126/humgen/projects/interval_rna/interval_rna_seq/thomasVDS/lof_missense/phenotypes/rna_seq/processed_v97/covariates/master/master_covariates_v97_swapd_depth_fastq_rin_cell_sex_pcs_season_batch_fc_pipelines_updtd.tsv\"\n",
    "input_path = Path(input_dir)\n",
    "output_dir_path = input_path.joinpath(\"misexp_metrics\")\n",
    "output_dir_path.mkdir(parents=True, exist_ok=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "a2b59c54",
   "metadata": {},
   "outputs": [],
   "source": [
    "# variables \n",
    "mixexp_tpm_cutoff = 0.5\n",
    "zscore_cutoffs = [2, 10, 20, 30, 40]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "23640920",
   "metadata": {},
   "outputs": [],
   "source": [
    "input_path = Path(input_dir)\n",
    "output_dir_path = input_path.joinpath(\"misexp_metrics\")\n",
    "output_dir_path.mkdir(parents=True, exist_ok=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "d632f129",
   "metadata": {},
   "outputs": [],
   "source": [
    "## load gene expression matrix\n",
    "tpm_zscore_flat_path = input_path.joinpath(\"misexp_gene_cov_corr/tpm_zscore_4568smpls_8610genes_flat_misexp_corr_qc.csv\")\n",
    "tpm_zscore_flat_df = pd.read_csv(tpm_zscore_flat_path)\n",
    "# include genes with all zeroes here "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "2833e7cd",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Number of inactive genes passing QC: 8650\n"
     ]
    }
   ],
   "source": [
    "# all inactive genes passing QC \n",
    "inactive_gene_id_pass_qc_path = wkdir_path.joinpath(\"2_misexp_qc/misexp_gene_cov_corr/gene_id_post_tech_cov_qc_8650.txt\")\n",
    "inactive_gene_id_pass_qc = pd.read_csv(inactive_gene_id_pass_qc_path, sep=\"\\t\", header=None)[0].tolist()\n",
    "num_inactive_gene_id_pass_qc = len(inactive_gene_id_pass_qc)\n",
    "print(f\"Number of inactive genes passing QC: {len(inactive_gene_id_pass_qc)}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "fd8d42aa",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Number of genes in gene expression matrix: 8610\n",
      "Number of samples in gene expression matrix: 4568\n"
     ]
    }
   ],
   "source": [
    "genes_pass_qc = tpm_zscore_flat_df.gene_id.unique()\n",
    "gene_number = len(genes_pass_qc)\n",
    "print(f\"Number of genes in gene expression matrix: {gene_number}\") # removed 40 with TPM = 0 across all samples\n",
    "smpl_pass_qc = tpm_zscore_flat_df.rna_id.unique()\n",
    "smpl_number = len(smpl_pass_qc)\n",
    "print(f\"Number of samples in gene expression matrix: {smpl_number}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "9ab29ed0",
   "metadata": {},
   "outputs": [],
   "source": [
    "inactive_genes_path = output_dir_path.joinpath(f\"inactive_genes_{gene_number}.txt\")\n",
    "with open(inactive_genes_path, 'w') as f_out:\n",
    "    for gene in genes_pass_qc: \n",
    "        f_out.write(f\"{gene}\\n\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "023aaede",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Total number of possible misexpression events: 39513200\n",
      "Total events with TPM > 0.1: 363951\n"
     ]
    }
   ],
   "source": [
    "# add gene-smpl pairs that have TPM = 0 for all genes \n",
    "total_events = len(inactive_gene_id_pass_qc) * len(smpl_pass_qc)\n",
    "print(f\"Total number of possible misexpression events: {total_events}\")\n",
    "\n",
    "# number of events with a TPM > 0.1\n",
    "total_events_grtr_tpm1 = tpm_zscore_flat_df[tpm_zscore_flat_df.TPM > 0.1].shape[0]\n",
    "print(f\"Total events with TPM > 0.1: {total_events_grtr_tpm1}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "3a1e8dd8",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Z-score cutoff: 2\n",
      "\tNumber of misexpression events: 28956\n",
      "\tNumber of misexpressed genes: 4437\n",
      "\tNumber of never misexpressed genes: 4213\n",
      "\tNumber of samples with a misexpression event: 4386/4568\n",
      "\tPercentage of samples with misexpression event: 96.01576182136601\n",
      "\tPercentage of genes-sample pairs misexpressed: 0.0732818399927113%\n",
      "\tPercentage of genes with at least one misexpression event: 51.29479768786127%\n",
      "\tMedian number of misexpression events: 4.0\n",
      "Z-score cutoff: 10\n",
      "\tNumber of misexpression events: 17461\n",
      "\tNumber of misexpressed genes: 4437\n",
      "\tNumber of never misexpressed genes: 4213\n",
      "\tNumber of samples with a misexpression event: 3511/4568\n",
      "\tPercentage of samples with misexpression event: 76.86077057793345\n",
      "\tPercentage of genes-sample pairs misexpressed: 0.04419029590111659%\n",
      "\tPercentage of genes with at least one misexpression event: 51.29479768786127%\n",
      "\tMedian number of misexpression events: 2.0\n",
      "Z-score cutoff: 20\n",
      "\tNumber of misexpression events: 7495\n",
      "\tNumber of misexpressed genes: 3891\n",
      "\tNumber of never misexpressed genes: 4759\n",
      "\tNumber of samples with a misexpression event: 2014/4568\n",
      "\tPercentage of samples with misexpression event: 44.08931698774081\n",
      "\tPercentage of genes-sample pairs misexpressed: 0.018968344755676585%\n",
      "\tPercentage of genes with at least one misexpression event: 44.982658959537574%\n",
      "\tMedian number of misexpression events: 0.0\n",
      "Z-score cutoff: 30\n",
      "\tNumber of misexpression events: 3154\n",
      "\tNumber of misexpressed genes: 2610\n",
      "\tNumber of never misexpressed genes: 6040\n",
      "\tNumber of samples with a misexpression event: 1113/4568\n",
      "\tPercentage of samples with misexpression event: 24.365148861646237\n",
      "\tPercentage of genes-sample pairs misexpressed: 0.00798214267637144%\n",
      "\tPercentage of genes with at least one misexpression event: 30.173410404624278%\n",
      "\tMedian number of misexpression events: 0.0\n",
      "Z-score cutoff: 40\n",
      "\tNumber of misexpression events: 1218\n",
      "\tNumber of misexpressed genes: 1205\n",
      "\tNumber of never misexpressed genes: 7445\n",
      "\tNumber of samples with a misexpression event: 599/4568\n",
      "\tPercentage of samples with misexpression event: 13.112959719789844\n",
      "\tPercentage of genes-sample pairs misexpressed: 0.0030825141977870686%\n",
      "\tPercentage of genes with at least one misexpression event: 13.930635838150291%\n",
      "\tMedian number of misexpression events: 0.0\n"
     ]
    }
   ],
   "source": [
    "misexp_metrics_dict = {}\n",
    "\n",
    "for row, zscore in enumerate(zscore_cutoffs): \n",
    "    print(f\"Z-score cutoff: {zscore}\")\n",
    "    ### Identify misexpression events \n",
    "    misexp_events_df = tpm_zscore_flat_df[(tpm_zscore_flat_df.TPM > mixexp_tpm_cutoff) &\n",
    "                                         (tpm_zscore_flat_df[\"z-score\"] > zscore)]\n",
    "    \n",
    "    total_misexp_events = misexp_events_df.shape[0]\n",
    "    print(f\"\\tNumber of misexpression events: {total_misexp_events}\")\n",
    "    \n",
    "    # misexpressed genes and never misexpressed genes at z-score cutoff \n",
    "    misexp_genes = misexp_events_df.gene_id.unique()\n",
    "    num_misexp_genes = len(misexp_genes)\n",
    "    print(f\"\\tNumber of misexpressed genes: {num_misexp_genes}\")\n",
    "    misexp_gene_path = output_dir_path.joinpath(f\"misexp_genes_tpm{mixexp_tpm_cutoff}_z{zscore}.txt\")\n",
    "    with open(misexp_gene_path, 'w') as misexp_genes_out:\n",
    "        for gene_id in misexp_genes: \n",
    "            misexp_genes_out.write(f\"{gene_id}\\n\")\n",
    "\n",
    "    # note using all 8650 inactive genes not just genes in matrix \n",
    "    never_misexp_genes = [gene_id for gene_id in inactive_gene_id_pass_qc if gene_id not in misexp_genes]\n",
    "    num_never_misexp_genes = len(never_misexp_genes)\n",
    "    print(f\"\\tNumber of never misexpressed genes: {num_never_misexp_genes}\")\n",
    "    never_misexp_gene_path = output_dir_path.joinpath(f\"never_misexp_genes_tpm{mixexp_tpm_cutoff}_z{zscore}.txt\")\n",
    "    with open(never_misexp_gene_path, 'w') as never_misexp_genes_out:\n",
    "        for gene_id in never_misexp_genes: \n",
    "            never_misexp_genes_out.write(f\"{gene_id}\\n\")\n",
    "    \n",
    "    # percentage of samples with a misexpression event \n",
    "    smpls_with_misexp = misexp_events_df.rna_id.unique()\n",
    "    num_smpls_with_misexp = len(smpls_with_misexp)\n",
    "    perc_smpls_with_misexp = (num_smpls_with_misexp/smpl_number) * 100\n",
    "    print(f\"\\tNumber of samples with a misexpression event: {num_smpls_with_misexp}/{smpl_number}\")\n",
    "    print(f\"\\tPercentage of samples with misexpression event: {perc_smpls_with_misexp}\")\n",
    "    # percentage of gene-sample pairs misexpressed \n",
    "    pc_gene_smpl_misexp = (total_misexp_events/total_events) * 100\n",
    "    print(f\"\\tPercentage of genes-sample pairs misexpressed: {pc_gene_smpl_misexp}%\")\n",
    "    # percentage of genes with at least one misexpression event \n",
    "    pc_genes_misexp = (num_misexp_genes/num_inactive_gene_id_pass_qc) * 100\n",
    "    print(f\"\\tPercentage of genes with at least one misexpression event: {pc_genes_misexp}%\")\n",
    "    \n",
    "    ### median misexpression events per sample \n",
    "    count_misexp_per_smpl_df = pd.DataFrame(misexp_events_df.groupby(by=\"rna_id\")[\"gene_id\"].count())\n",
    "    count_misexp_per_smpl_df = count_misexp_per_smpl_df.rename(columns={\"gene_id\":\"misexp_count\"})\n",
    "    rna_id_zero_count_dict = {rna_id:0 for rna_id in smpl_pass_qc if rna_id not in smpls_with_misexp}\n",
    "    rna_id_zero_count_df = pd.DataFrame.from_dict(rna_id_zero_count_dict, orient=\"index\")\n",
    "    rna_id_zero_count_df = rna_id_zero_count_df.rename(columns={0:\"misexp_count\"})\n",
    "    count_misexp_per_smpl_df = pd.concat([count_misexp_per_smpl_df, rna_id_zero_count_df])\n",
    "    if count_misexp_per_smpl_df.misexp_count.sum() != total_misexp_events:\n",
    "        raise ValueError(f\"Sum of misexpression events per sample is not equal to total misexpression events.\")\n",
    "    median_misexp = count_misexp_per_smpl_df.misexp_count.median()\n",
    "    print(f\"\\tMedian number of misexpression events: {median_misexp}\")\n",
    "    \n",
    "    # add information \n",
    "    misexp_metrics_dict[row] = [zscore, num_smpls_with_misexp, perc_smpls_with_misexp, total_misexp_events,\n",
    "                                pc_gene_smpl_misexp, num_misexp_genes, pc_genes_misexp, median_misexp]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "db8fcc9b",
   "metadata": {},
   "outputs": [],
   "source": [
    "misexp_metrics_cols = [\"zscore\", \"smpl_misexp\", \"smpl_misexp_perc\", \"gene_smpl_misexp\",\n",
    "                       \"gene_smpl_misexp_perc\", \"gene_misexp\", \"gene_misexp_perc\", \"median_misexp\"]\n",
    "misexp_metrics_df = pd.DataFrame.from_dict(misexp_metrics_dict, orient=\"index\", columns=misexp_metrics_cols)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "2dd4b49a",
   "metadata": {},
   "outputs": [],
   "source": [
    "# write results to file\n",
    "misexp_metrics_path = output_dir_path.joinpath(\"misexp_metrics.csv\")\n",
    "misexp_metrics_df.to_csv(misexp_metrics_path, index=False)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e8374f6c",
   "metadata": {},
   "source": [
    "### Downsampling to see number of misexpressed genes "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "c1fd3cd3",
   "metadata": {},
   "outputs": [],
   "source": [
    "# list of samples \n",
    "num_misexp_genes_downsample = {}\n",
    "smpl_pass_qc_set = set(smpl_pass_qc)\n",
    "# loop \n",
    "count = 0 \n",
    "for sample in [500, 1000, 1500, 2000, 2500, 3000, 3500, 4000, 4500]:\n",
    "    permut = 1\n",
    "    while permut < 6: \n",
    "        # randomly select samples\n",
    "        random_samples = random.sample(smpl_pass_qc_set, sample)\n",
    "        random_samples_tpm_zscore_df = tpm_zscore_flat_df[tpm_zscore_flat_df.rna_id.isin(random_samples)]\n",
    "        # recalculate z-score \n",
    "        \n",
    "        misexp_df = random_samples_tpm_zscore_df[(random_samples_tpm_zscore_df.TPM > 0.5)# &\n",
    "                                                 #(random_samples_tpm_zscore_df[\"z-score\"] > 2)\n",
    "                                                ]\n",
    "        # count number of genes misexpressed \n",
    "        misexp_gene_id = misexp_df.gene_id.unique()\n",
    "        num_misexp_gene_id = len(misexp_gene_id)\n",
    "        num_misexp_genes_downsample[count] = [sample, permut, num_misexp_gene_id]\n",
    "\n",
    "        permut += 1\n",
    "        count += 1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "4588dfdc",
   "metadata": {},
   "outputs": [],
   "source": [
    "num_misexp_genes_downsample_df = pd.DataFrame.from_dict(num_misexp_genes_downsample, orient=\"index\", columns=[\"samples\", \"permut\", \"misexp_genes\"])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "a4fdc5c1",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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CX71EB09elRDhgxpdLxDhw6qrq6+6aQA+MfhcKigoCDg13W73dYzzDZu3CiHwxHw7wjGNQHAV34VRGlpafroo48aLbHftWuX7rzzzkDkBcAPNpvN5wekGmOC9uT6K3iCPYBI4VdB9Nhjj+mJJ57Q//pf/0s2m02nTp1SUVGRFixYoB//+MeBzhFAELjdbmVnZzf7c8152j1PsAcQKfwqiJ566im5XC4NHz5cbrdbQ4YMkd1u14IFCzRr1qxA5wgAABBUNmOMuXFY0y5evKgPPvhADQ0N6tOnj9q3bx/I3MJKTU2NnE6nXC6XOnToEOp0gJvWnCEzY4y1mtRut/s8DMaQGYBQ8/Xvt189RFe0bdtWAwYMuJlLAAiR5sw3kr749x0AWiu/CqILFy7oueee03/+53+qsrJSDQ0NXuc//vjjgCQHAADQEvwqiB599FHt2LFDeXl5SktLo0scAABENL8Koi1btmjz5s36xje+Eeh8AAAAWpxfO1V37NhRSUlJgc4FAAAgJPwqiH7605/qxz/+sS5evBjofAAAAFqcX0NmL774ov76178qJSVFt99+u9fzzCTxPDMAABBR/CqIHnzwwUDnAQAAEDI3tTFjNGFjRgAAIo+vf7/9mkMkSdXV1frd736nhQsX6vPPP5f0xVDZZ5995u8lAQAAQsKvIbODBw9q1KhRcjqdOnHihKZPn66kpCRt2LBBn3zyiV577bVA5wkAABA0fvUQzZs3T1OnTtWxY8fkcDis42PGjNHOnTsDlhwAAEBL8Ksg2rdvnx577LFGx2+99VZVVFTcdFIAAAAtya+CyOFwqKamptHxo0ePqkuXLjedFAAAQEvyqyAaN26c/u3f/k2XLl2S9MVTsz/99FP967/+qx566KGAJggAABBsfhVEv/jFL3TmzBklJyertrZWQ4cOVffu3ZWYmKif/exngc4RAAAgqPxaZdahQwft2rVL7777rvbv36+GhgZ9/etf16hRowKdHwAAQNCxMaOP2JgRAIDI4+vfb796iH796183edxms8nhcKh79+4aMmSIYmJi/Lk8AABAi/KrIFq2bJnOnDmjixcvqmPHjjLGqLq6Wm3btlX79u1VWVmpO++8U++9954yMjICnTMAAEBA+TWpesmSJbrnnnt07NgxnT17Vp9//rn+8pe/aODAgfrVr36lTz/9VKmpqXry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J4e8vWPGjNHDDz+sbt266fjx43r66ac1YsQIFRcXy263R0T7jDGaN2+e7r33XmVmZlo5XcnzapF275pqmxTZ9620tFRZWVlyu91q3769NmzYoD59+lh/FCL5nl2vbVJk3zNJWrt2rfbv3699+/Y1Ohfp/759WdukyLx3FEQtZMyYMdb7vn37KisrS1/5ylf0+9//3ppoZrPZvD5jjGl07Fq+xIRCINrSVHw4tHfixInW+8zMTA0YMEDdunXT5s2bNX78+Ot+LpzaN2vWLB08eFC7du1qdC7S79312hbJ961Xr14qKSlRdXW11q9frylTpmjHjh3XzSmS7tn12tanT5+IvmdlZWV64okntHXrVjkcjuvGReK986VtkXjvGDILkXbt2qlv3746duyYtdrs2oq3srLS+n8PqampqqurU1VV1XVjwkGg2pKamqrTp083uv6ZM2fCqr2SlJaWpm7duunYsWOSwr99s2fP1ltvvaX33ntPXbt2tY63hnt3vbY1JZLuW3x8vLp3764BAwZo6dKluvvuu/WrX/2qVdyz67WtKZF0z4qLi1VZWan+/fsrNjZWsbGx2rFjh379618rNjbW+u5IvHc3alt9fX2jz0TCvaMgChGPx6MjR44oLS1Nd9xxh1JTU7Vt2zbrfF1dnXbs2KHBgwdLkvr376+4uDivmPLych06dMiKCQeBaktWVpZcLpf27t1rxezZs0culyus2itJZ8+eVVlZmdLS0iSFb/uMMZo1a5b+9Kc/6d1339Udd9zhdT6S792N2taUSLlvTTHGyOPxRPQ9u54rbWtKJN2zkSNHqrS0VCUlJdZrwIABmjx5skpKSnTnnXdG7L27UdtiYmIafSYi7l3Ap2mjSfPnzzfbt283H3/8sdm9e7cZO3asSUxMNCdOnDDGfLH80ul0mj/96U+mtLTUPPLII00uv+zatat55513zP79+82IESNCsuz+3Llz5sCBA+bAgQNGknnppZfMgQMHzCeffBLQtuTk5Jh+/fqZoqIiU1RUZPr27dsiS0m/rH3nzp0z8+fPN4WFheb48ePmvffeM1lZWebWW28N+/Y9/vjjxul0mu3bt3sthb148aIVE6n37kZti+T7tnDhQrNz505z/Phxc/DgQbNo0SLTpk0bs3XrVmNM5N6zG7Utku/Z9Vy7EiuS792XtS1S7x0FUQu5sr9EXFycSU9PN+PHjzeHDx+2zjc0NJif/OQnJjU11djtdjNkyBBTWlrqdY3a2loza9Ysk5SUZBISEszYsWPNp59+2tJNMe+9956R1Og1ZcqUgLbl7NmzZvLkySYxMdEkJiaayZMnm6qqqpC27+LFi2b06NGmS5cuJi4uztx2221mypQpjXIPx/Y11SZJZtWqVVZMpN67G7Utku/bd7/7XdOtWzcTHx9vunTpYkaOHGkVQ8ZE7j27Udsi+Z5dz7UFUSTfu2td3bZIvXc2Y4wJfL8TAABA5GAOEQAAiHoURAAAIOpREAEAgKhHQQQAAKIeBREAAIh6FEQAACDqURABAICoR0EEAACiHgURADTD1KlT9eCDD4Y6DQABRkEEAACiHgURAACIehREAMLWH//4R/Xt21cJCQnq1KmTRo0apQsXLmjfvn2677771LlzZzmdTg0dOlT79+/3+qzNZtPKlSs1duxYtW3bVr1791ZRUZE++ugjDRs2TO3atVNWVpb++te/Wp9ZvHixvvrVr2rlypXKyMhQ27Zt9fDDD6u6uvq6ORpj9Pzzz+vOO+9UQkKC7r77bv3xj3+0zldVVWny5Mnq0qWLEhIS1KNHD61atSrwvywAN4WCCEBYKi8v1yOPPKLvfve7OnLkiLZv367x48fLGKNz585pypQp+vOf/6zdu3erR48euv/++3Xu3Dmva/z0pz/Vd77zHZWUlOjv/u7vNGnSJD322GNauHCh3n//fUnSrFmzvD7z0Ucf6f/8n/+jTZs2KT8/XyUlJZo5c+Z18/zRj36kVatWacWKFTp8+LCefPJJffvb39aOHTskSU8//bQ++OADbdmyRUeOHNGKFSvUuXPnAP+2ANw0AwBhqLi42EgyJ06cuGHs5cuXTWJiotm0aZN1TJL50Y9+ZP1cVFRkJJlXX33VOva///f/Ng6Hw/r5Jz/5iYmJiTFlZWXWsS1btpg2bdqY8vJyY4wxU6ZMMePGjTPGGHP+/HnjcDhMYWGhVz7Tpk0zjzzyiDHGmG9+85vmn//5n5vTdAAhQA8RgLB09913a+TIkerbt68efvhhvfLKK6qqqpIkVVZW6nvf+5569uwpp9Mpp9Op8+fP69NPP/W6Rr9+/az3KSkpkqS+fft6HXO73aqpqbGO3Xbbberatav1c1ZWlhoaGnT06NFGOX7wwQdyu92677771L59e+v12muvWUNxjz/+uNauXauvfvWreuqpp1RYWBiA3w6AQIsNdQIA0JSYmBht27ZNhYWF2rp1q/793/9dP/zhD7Vnzx7NnDlTZ86c0S9/+Ut169ZNdrtdWVlZqqur87pGXFyc9d5ms133WENDw3XzuBJz5X+vduVzmzdv1q233up1zm63S5LGjBmjTz75RJs3b9Y777yjkSNHaubMmfrFL37h8+8CQPDRQwQgbNlsNn3jG9/QM888owMHDig+Pl4bNmzQn//8Z82ZM0f333+/7rrrLtntdv3tb38LyHd++umnOnXqlPVzUVGR2rRpo549ezaK7dOnj+x2uz799FN1797d65WRkWHFdenSRVOnTtUbb7yhX/7yl3r55ZcDkiuAwKGHCEBY2rNnj/7zP/9To0ePVnJysvbs2aMzZ86od+/e6t69u15//XUNGDBANTU1+pd/+RclAJQQdAAAAVFJREFUJCQE5HsdDoemTJmiX/ziF6qpqdGcOXM0YcIEpaamNopNTEzUggUL9OSTT6qhoUH33nuvampqVFhYqPbt22vKlCn68Y9/rP79++uuu+6Sx+PR//t//0+9e/cOSK4AAoeCCEBY6tChg3bu3Klf/vKXqqmpUbdu3fTiiy9qzJgxSk1N1YwZM/S1r31Nt912m5YsWaIFCxYE5Hu7d++u8ePH6/7779fnn3+u+++/X//xH/9x3fif/vSnSk5O1tKlS/Xxxx/rlltu0de//nUtWrRIkhQfH6+FCxfqxIkTSkhI0D/8wz9o7dq1AckVQODYjDEm1EkAQDhYvHix3nzzTZWUlIQ6FQAtjDlEAAAg6lEQAQCAqMeQGQAAiHr0EAEAgKhHQQQAAKIeBREAAIh6FEQAACDqURABAICoR0EEAACiHgURAACIehREAAAg6v3/NJQEi3Q1isMAAAAASUVORK5CYII=\n",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "sns.boxplot(data=num_misexp_genes_downsample_df, x=\"samples\", y=\"misexp_genes\", showfliers=False)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "fbe9f7b1",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.7"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
